package cn.xxm.scene.service.impl;

import cn.xxm.scene.bo.UserBo;
import cn.xxm.scene.common.base.BaseResponse;
import cn.xxm.scene.common.base.ExceptionCodeEum;
import cn.xxm.scene.dao.UserDao;
import cn.xxm.scene.dao.UserTokenDao;
import cn.xxm.scene.dto.input.LoginInputDTO;
import cn.xxm.scene.dto.input.RoleInputDTO;
import cn.xxm.scene.dto.input.UserInfoInputDTO;
import cn.xxm.scene.dto.output.LoginOutputDTO;
import cn.xxm.scene.dto.output.UserInfoOutputDTO;
import cn.xxm.scene.entity.User;
import cn.xxm.scene.entity.UserToken;
import cn.xxm.scene.exception.ExceptionCast;
import cn.xxm.scene.service.UserService;
import cn.xxm.scene.utils.RedisKeyUtils;
import cn.xxm.scene.utils.RedisUtil;
import cn.xxm.scene.utils.StringUtil;
import cn.xxm.scene.utils.XxmBeanUtils;
import cn.xxm.scene.validate.response.FSResponseModel;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.plugins.Page;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author Xxm123
 * @since 2020-02-22
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserDao, User> implements UserService {


    @Autowired
    private UserTokenDao userTokenDao;

    @Autowired
    private UserDao userDao;

    @Autowired
    private RedisUtil redisUtil;

    @Override
    @Transactional
    public FSResponseModel login(LoginInputDTO inputDTO) {
        // 1. 校验账密
        User user = checkUserNamePwd(inputDTO);

        // 2. 生成token
        String token = StringUtil.getUUID();

        // 3. 插入user_token
        recordUserToken(inputDTO, user, token);

        // 4. 返回data
        LoginOutputDTO data = new LoginOutputDTO();
        data.setToken(token);
        return FSResponseModel.ok(data);
    }

    @Override
    public BaseResponse getUserList(UserInfoInputDTO inputDTO) {
        Page page = new Page<>(inputDTO.getPagenum(), inputDTO.getPagesize());
        if (inputDTO != null && StringUtils.isNotEmpty(inputDTO.getQuery())) {
            inputDTO.setQuery(inputDTO.getQuery().trim());
        }

        List<UserBo> userList = userDao.selectUserRoleByPage(page, inputDTO);

        UserInfoOutputDTO data = new UserInfoOutputDTO();
        data.setTotal(page.getTotal());
        data.setTotalPage(page.getPages());
        data.setUsers(userList);
        return BaseResponse.ok(data);
    }

    @Override
    public BaseResponse getUserById(String id) {
        UserInfoInputDTO inputDTO = new UserInfoInputDTO();
        inputDTO.setId(id);
        Page page = new Page(1, 1);
        List<UserBo> userList = userDao.selectUserRoleByPage(page, inputDTO);
        UserBo userBo = CollectionUtils.isEmpty(userList) ? null : userList.get(0);

        return BaseResponse.ok(userBo);
    }


    @Override
    public BaseResponse updateUserById(UserInfoInputDTO infoInputDTO) {
        User user = XxmBeanUtils.E2T(infoInputDTO, User.class);
        // 1.姓名不让修改
        user.setUsername(null);
        user.setId(Long.parseLong(infoInputDTO.getId()));
        Integer integer = userDao.updateById(user);

        return BaseResponse.ok("修改成功");
    }

    @Override
    public BaseResponse deleteUserById(String id) {
        int row = userDao.deleteUserAndRoleBy(id);
        if (row > 0) {
            return BaseResponse.ok();
        } else {
            return BaseResponse.error("删除失败");
        }
    }

    @Override
    @Transactional
    public BaseResponse updateRoleById(RoleInputDTO roleInputDTO) {
        userDao.deleteUserRoleByUserId(roleInputDTO);
        userDao.insertUserRoleById(roleInputDTO);
        User user = new User();
        user.setUpdateDate(new Date());
        user.setId(Long.parseLong(roleInputDTO.getUid()));
        userDao.updateById(user);
        return BaseResponse.ok();
    }



    @Override
    public BaseResponse saveUser(UserInfoInputDTO inputDTO) {
        User user = XxmBeanUtils.E2T(inputDTO, User.class);
        user.setCreateDate(new Date());
        user.setUpdateDate(new Date());
        user.setStatus(inputDTO.isState()?1:0);
        Integer row = userDao.insert(user);
        if(row>0){
            return BaseResponse.ok();
        }
        return BaseResponse.error("新增用户失败");
    }

    @Override
    public BaseResponse updateUserStatus(String uid, boolean flag) {
        User user = new User();
        user.setId(Long.parseLong(uid));
        user.setStatus(flag?1:0);
        user.setUpdateDate(new Date());
        Integer row = userDao.updateById(user);
        if(row == 0 ){
            return BaseResponse.error("修改用户状态失败");
        }
        return BaseResponse.ok();
    }


    /**
     * 校验账密
     *
     * @param inputDTO
     * @return
     */
    private User checkUserNamePwd(LoginInputDTO inputDTO) {
        List<User> userList = userDao.selectByConditions(inputDTO);
        if (CollectionUtils.isEmpty(userList)) {
            ExceptionCast.cast(ExceptionCodeEum.USERNAME_OR_PWD_INCORRECT);
        }
        return userList.get(0);
    }


    /**
     * 记录用户登录流水
     *
     * @param inputDTO
     * @param user
     * @param token
     */
    private void recordUserToken(LoginInputDTO inputDTO, User user, String token) {
        // 失效当前clientType&userId的所有记录
        Map queryMap = new HashMap<>();
        queryMap.put("clientType", inputDTO.getClientType());
        queryMap.put("userId", user.getId());
        userTokenDao.disableClientStatus(queryMap);

        UserToken userToken = new UserToken();
        userToken.setToken(token);
        userToken.setClientType(inputDTO.getClientType());
        userToken.setLoginType(inputDTO.getLoginType());
        userToken.setUserId(user.getId());
        userToken.setCreateTime(new Date());
        userToken.setUpdateTime(new Date());
        userToken.setIsAvailable(1);
        userTokenDao.insert(userToken);

        String userTokenKey = RedisKeyUtils.getUserTokenKey(token);
        redisUtil.setString(userTokenKey, JSONObject.toJSONString(user), RedisKeyUtils.LOGIN_SESSION_EXPIRE);
    }
}
